/**
 * Wrapper class for the google maps service.
 * 
 * @author Kim Pommert
 * @version %I%, %G%
 */
qx.Class.define("qooxdoosample.google.maps.GMapsWrapper",
{
	extend: qx.core.Object,
	implement: qooxdoosample.cocktail.maps.IDynamicMap,
	
	/**
	 * Class constructor.
	 * Instantiates an object of that class.
	 * 
	 * @param mapContainerId	{String} ID of the div container the map will be deployed to
	 */
	construct: function(mapContainerId)
	{
		this.base(arguments);
		this.setGMap(new GMap2(document.getElementById(mapContainerId)));
    },
    
    statics:
    {
    	/**
    	 * Every load map request needs a zoom level. If no specific level
    	 * is given, this value is used.
    	 */
    	DEFAULT_ZOOM_LEVEL: 13
    },
    
    properties:
    {
    	/**
    	 * The google maps object.
    	 */
    	gMap:
    	{
    		nullable: true,
    		init: null,
    		check: "GMap2"
    	},
    	
    	/**
    	 * An array that contains several google control panels that will be displayed
    	 * when calling the showControls() method.
    	 */
    	gControls:
    	{
    		nullable: true,
    		init: null,
    		check: "Array"
    	}
    },
	
	members:
	{
		
		/**
		 * Get the google map object
		 * 
		 * @return	{Object} The GMap object
		 * @see qooxdoosample.cocktail.maps.IMap#getMap()
		 */
		getMap: function()
		{
			return this.getGMap();
		},
		
		/**
		 * Set the google map object.
		 * 
		 * @param value	{Object} the GMap object
		 * @see qooxdoosample.cocktail.maps.IMap#setMap()
		 */
		setMap: function(value)
		{
			this.setGMap(value);
		},
		
		/**
		 * Set the center of the map to the specified coordinates.
		 * 
		 * @param position	{qooxdoosample.cocktail.util.LatLng} Coordinates for new center of the map
		 * @see qooxdoosample.cocktail.maps.IMap#setCenter()
		 */
		setCenter: function(position)
		{
			this.getGMap().setCenter(this.__convertLatLngToGoogleFormat(position), this.self(arguments).DEFAULT_ZOOM_LEVEL);
		},
		
		/**
		 * Get the current position the map is centered on.
		 * 
		 * @return	{qooxdoosample.cocktail.util.LatLng} Coordinates of the current center point
		 * @see qooxdoosample.cocktail.maps.IMap#getCenter()
		 */
		getCenter: function()
		{
			var gLatLng = this.getGMap().getCenter();
			return new qooxdoosample.cocktail.util.LatLng(gLatLng.lat(), gLatLng.lng()); 
		},
		
		/**
		 * Set the zoom level of the map.
		 * 
		 * @param level	{Number} The zoom level
		 * @see qooxdoosample.cocktail.maps.IMap#setZoomLevel()
		 */
		setZoomLevel: function(level)
		{
			this.getGMap().setZoom(level);
		},
		
		/**
		 * Get the current zoom level of the map
		 * 
		 * @return	{Number} The zoom level
		 * @see qooxdoosample.cocktail.maps.IMap#getZoomLevel()
		 */
		getZoomLevel: function()
		{
			return this.getGMap().getZoom();
		},
		
		/**
		 * Get the current coordinates of the south west and north east corner of the map.
		 * 
		 * @return	{qooxdoosample.cocktail.util.Boundaries} The boundaries of the map 
		 * @see qooxdoosample.cocktail.maps.IMap#getMapBoundaries()
		 */
		getMapBoundaries: function()
		{
			var gBounds = this.getGMap().getBounds();
			var gSW = gBounds.getSouthWest();
			var gNE = gBounds.getNorthEast();
			
			var southWest = new qooxdoosample.cocktail.util.LatLng(gSW.lat(), gSW.lng());
			var northEast = new qooxdoosample.cocktail.util.LatLng(gNE.lat(), gNE.lng());
			
			return new qooxdoosample.cocktail.util.Boundaries(southWest, northEast); 
		},
		
		/**
		 * Display the default google maps control panel.
		 * 
		 * @see qooxdoosample.cocktail.maps.IMap#showControls()
		 */
		showControls: function()
		{
			if(this.getGControls() == null){
				/*
				 * no control panel initialized
				 * the elements will be created and stored in an array
				 */
				var mapType = new GMapTypeControl();
				var mapControl = new GLargeMapControl();
				
				// add control panels to map
				this.getGMap().addControl(mapType);
				this.getGMap().addControl(mapControl);
				this.setGControls(new Array(mapType, mapControl));
			} 
			
		},
		
		/**
		 * Hide the google maps control panel.
		 * 
		 * @see qooxdoosample.cocktail.maps.IMap#hideControls()
		 */
		hideControls: function()
		{
			var controls = this.getGControls();
			if(controls != null){
				for(i = 0; i < controls.length; i++)
				{
					this.getGMap().removeControl(controls[i]);
				}
				this.setGControls(null);
			}
		},
		
		/**
		 * Add an overlay to the map.
		 * Typical overlays are Markers, Routes or Shapes.
		 * 
		 * @param overlay	{qooxdoosample.cocktail.util.overlays.Overlay} The overlay that will be added to the map
		 * @see qooxdoosample.cocktail.maps.IMap#addOverlay()
		 */
		addOverlay: function(overlay)
		{
			if(overlay instanceof qooxdoosample.cocktail.util.overlays.Marker)
			{
				// set the markers icon
				var overlayIcon = new GIcon(G_DEFAULT_ICON);
				if(overlay.getCustomIcon() != null){
					customIcon = overlay.getCustomIcon();
					overlayIcon.image = customIcon.getImage();
					overlayIcon.iconSize = new GSize(customIcon.getWidth(), customIcon.getHeight());
				}
                
				// Set up GMarkerOptions object
				markerOptions = { icon:overlayIcon, draggable: overlay.getDraggable()};
				
				// get markers position
				var gPoint = this.__convertLatLngToGoogleFormat(overlay.getPosition());
				
				var marker = new GMarker(gPoint, markerOptions);
				
				if(overlay.getInfoText() != null){
					GEvent.addListener(marker, "click", function() {
    					marker.openInfoWindowHtml(overlay.getInfoText());
  					});
				}
				
				// add marker to map
				this.getGMap().addOverlay(marker);
				
			} 
			else if(overlay instanceof qooxdoosample.cocktail.util.overlays.Polygon)
			{		
				var gPoints = new Array();
				var points = overlay.getPoints();
				
				for(i=0; i< points.length; i++)
				{
					gPoints[i] = this.__convertLatLngToGoogleFormat(points[i]);
				}
				
				var polygon = new GPolygon(gPoints, 
											overlay.getColor(), 
											overlay.getWidth(),
											overlay.getLineOpacity(), 
											overlay.getFillColor(), 
											overlay.getFillOpacity());
				this.getGMap().addOverlay(polygon);
			}
			else if(overlay instanceof qooxdoosample.cocktail.util.overlays.Polyline)
			{
				// get all points of the polyline and convert them to google format
				var gPoints = new Array();
				var points = overlay.getPoints();
				
				for(i=0; i< points.length; i++)
				{
					gPoints[i] = this.__convertLatLngToGoogleFormat(points[i]);
				}
				
				// setup all polyline options
				var polyOptions = {geodesic:overlay.getGeodesic()};
				
				// create the polyline
				var polyline = new GPolyline(gPoints, 
												overlay.getColor(), 
												overlay.getWidth(), 
												overlay.getLineOpacity(),
												polyOptions);
					
				// add polyline to map							
				this.getGMap().addOverlay(polyline);	
			}
			
		},
		
		/**
		 * Remove all overlays from the map.
		 * 
		 * @see qooxdoosample.cocktail.maps.IMap#clearOverlays()
		 */
		clearOverlays: function()
		{
			this.getGMap().clearOverlays();	
		},
		
		/**
		 * Converts the generic geographic coordinates to google specific format.
		 * 
		 * @param value	{qooxdoosample.cocktail.util.LatLng} The coordinates
		 * @return	{Object} The coordinates in google format
		 */
		__convertLatLngToGoogleFormat: function(value)
		{
			return new GLatLng(value.getLatitude(), value.getLongitude());
		},
		
		/*
		 * MAP CONTROLS
		 */
		
		/**
		 * Change the displayed type of the map
		 * 
		 * @param type	{Number} Constant value of the map type
		 * @see qooxdoosample.cocktail.maps.IDynamicMap#setMapType()
		 */ 
		setMapType: function(type)
		{
			if(type == qooxdoosample.cocktail.maps.IDynamicMap.MAP_TYPE_NORMAL)
				this.getGMap().setMapType(G_NORMAL_MAP);
			else if(type == qooxdoosample.cocktail.maps.IDynamicMap.MAP_TYPE_SATELLITE)
				this.getGMap().setMapType(G_SATELLITE_MAP);
			else if(type == qooxdoosample.cocktail.maps.IDynamicMap.MAP_TYPE_HYBRID)
				this.getGMap().setMapType(G_HYBRID_MAP);
		},
		
		/**
		 * Increases the zoom level of the map
		 * 
		 * @see qooxdoosample.cocktail.maps.IDynamicMap#zoomIn()
		 */
		zoomIn: function()
		{
			this.getGMap().zoomIn();
		},
		
		/**
		 * Decreases the zoom level of the map
		 * 
		 * @see qooxdoosample.cocktail.maps.IDynamicMap#zoomOut()
		 */
		zoomOut: function()
		{
			this.getGMap().zoomOut();
		},
		
		/**
		 * Shifts the current map view to the west
		 * 
		 * @see qooxdoosample.cocktail.maps.IDynamicMap#moveLeft()
		 */
		moveLeft: function()
		{
			this.getGMap().panDirection(1, 0);
		},
		
		/**
		 * Shifts the current map view to the east
		 * 
		 * @see qooxdoosample.cocktail.maps.IDynamicMap#moveRight()
		 */
		moveRight: function()
		{
			this.getGMap().panDirection(-1, 0);
		},
		
		/**
		 * Shifts the current map view to the north
		 * 
		 * @see qooxdoosample.cocktail.maps.IDynamicMap#moveUp()
		 */
		moveUp: function()
		{
			this.getGMap().panDirection(0, 1);
		},
		
		/**
		 * Shifts the current map view to the south
		 * 
		 * @see qooxdoosample.cocktail.maps.IDynamicMap#moveDown()
		 */
		moveDown: function()
		{
			this.getGMap().panDirection(0, -1);
		}
		
	}
});